package captcha

import (
	"math/rand"
	"strconv"
	"time"

	"bbs/pkg/domain"
	"bbs/pkg/model/redis"
)

type captchaService struct {
	cacheSvc redis.RedisService
	emailSvc domain.EmailService
	tempSvc  domain.TemplateService
}

func NewCaptchaService(emailSvc domain.EmailService, cacheSvc redis.RedisService, tempSvc domain.TemplateService) domain.CaptchaService {
	return &captchaService{
		emailSvc: emailSvc,
		cacheSvc: cacheSvc,
		tempSvc:  tempSvc,
	}
}

func (svc *captchaService) SendByEmail(email string) error {
	// generate message
	code := svc.generate()
	message, err := svc.tempSvc.RenderCaptchaTemplate(code)
	if err != nil {
		return err
	}

	// send captcha email
	if err := svc.emailSvc.SendCaptcha(message, email); err != nil {
		return err
	}

	// save captcha
	if err := svc.save(email, code); err != nil {
		return err
	}

	return nil
}

func (svc *captchaService) VerifyEmailCaptcha(email, code string) (bool, error) {
	key := "email" + "_" + email
	value, err := svc.cacheSvc.Get(key)
	return code == value, err
}

func (svc *captchaService) generate() string {
	rand.Seed(time.Now().Unix())
	var code string
	for i := 0; i < 6; i++ {
		n := rand.Intn(10)
		code += strconv.Itoa(n)
	}
	return code
}

func (svc *captchaService) save(email, code string) error {
	key := "email" + "_" + email
	return svc.cacheSvc.SetString(key, code, 5*time.Minute)
}
